package org.deltaset.meta.internal;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *
 * @author dmakariev
 */
public class MetaClassBuilder<T> {

    private String id = null;
    private String scheme = null;
    private String originalType = null;
    private String collectionType = null;
    private Map<String, MetaActionImpl> actions = null;
    private Map<String, List<String>> actionsOrder = null;
    private Map<String, MetaFieldImpl> fields = null;
    private Map<String, List<String>> fieldsOrder = null;
    private MetaActionImpl defaultAction = MetaUtils.emptyMetaAction();
    private MetaActionImpl findByIdAction = MetaUtils.emptyMetaAction();
    private MetaFieldImpl idField = MetaUtils.emptyMetaField();
    private boolean isCollection = false;
    private boolean isVoid = false;
    private boolean isPojo = false;
    private boolean isEmpty = true;
    private T detail;

    public static <T> MetaClassImpl<T> primitive(Class primitiveClass, T detail) {

        final MetaClassBuilder<T> builder = MetaClassBuilder.newBuilder();
        return builder.originalType(primitiveClass.getName()).
                isEmpty(false).
                detail(detail).
                build();

    }

    public static MetaClassBuilder newBuilder() {
        return new MetaClassBuilder();
    }

    public MetaClassImpl build() {
        final Map<String, MetaActionImpl> resolvedActions = MetaUtils.defaultNull(actions, Collections.EMPTY_MAP);
        final Map<String, List<String>> resolvedActionsOrder = MetaUtils.defaultNull(actionsOrder, Collections.EMPTY_MAP);
        final Map<String, MetaFieldImpl> resolvedFields = MetaUtils.defaultNull(fields, Collections.EMPTY_MAP);
        final Map<String, List<String>> resolvedFieldsOrder = MetaUtils.defaultNull(fieldsOrder, Collections.EMPTY_MAP);
        final MetaClassImpl metaClassImpl = new MetaClassImpl(id, scheme, originalType, collectionType, resolvedActions, resolvedActionsOrder, resolvedFields, resolvedFieldsOrder, defaultAction, findByIdAction, idField, isCollection, isVoid, isPojo, isEmpty, detail);
        return metaClassImpl;
    }

    public MetaClassBuilder addAction(final MetaActionImpl metaActionImpl) {
        final String actionId = metaActionImpl.getId();
        if (null == this.actions) {
            this.actions = new HashMap<String, MetaActionImpl>();
        }
        this.actions.put(actionId, metaActionImpl);
        return this;
    }

    public MetaClassBuilder addField(final MetaFieldImpl metaFieldImpl) {
        final String fieldId = metaFieldImpl.getId();
        if (null == this.fields) {
            this.fields = new HashMap<String, MetaFieldImpl>();
        }
        this.fields.put(fieldId, metaFieldImpl);
        return this;
    }

    public MetaClassBuilder defaultActionOrder(List<String> actionOrder) {
        return addActionOrder(MetaUtils.DEFAULT, actionOrder);
    }

    public MetaClassBuilder addActionOrder(String viewName, List<String> actionOrder) {
        if (null == this.actionsOrder) {
            this.actionsOrder = new HashMap<String, List<String>>();
        }
        this.actionsOrder.put(viewName, actionOrder);
        return this;
    }

    public MetaClassBuilder defaultFieldOrder(List<String> fieldOrder) {
        return addFieldOrder(MetaUtils.DEFAULT, fieldOrder);
    }

    public MetaClassBuilder addFieldOrder(String viewName, List<String> fieldOrder) {
        if (null == this.fieldsOrder) {
            this.fieldsOrder = new HashMap<String, List<String>>();
        }
        this.fieldsOrder.put(viewName, fieldOrder);
        return this;
    }

    public MetaClassBuilder id(String id) {
        this.id = id;
        return this;
    }

    public MetaClassBuilder scheme(String scheme) {
        this.scheme = scheme;
        return this;
    }

    public MetaClassBuilder originalType(String originalType) {
        this.originalType = originalType;
        return this;
    }

    public MetaClassBuilder collectionType(String collectionType) {
        this.collectionType = collectionType;
        return this;
    }

    public MetaClassBuilder defaultAction(MetaActionImpl defaultAction) {
        this.defaultAction = defaultAction;
        return this;
    }

    public MetaClassBuilder findByIdAction(MetaActionImpl findByIdAction) {
        this.findByIdAction = findByIdAction;
        return this;
    }

    public MetaClassBuilder idField(MetaFieldImpl idField) {
        this.idField = idField;
        return this;
    }

    public MetaClassBuilder isCollection(boolean isCollection) {
        this.isCollection = isCollection;
        return this;
    }

    public MetaClassBuilder isVoid(boolean isVoid) {
        this.isVoid = isVoid;
        return this;
    }

    public MetaClassBuilder isPojo(boolean isPojo) {
        this.isPojo = isPojo;
        return this;
    }

    public MetaClassBuilder isEmpty(boolean isEmpty) {
        this.isEmpty = isEmpty;
        return this;
    }

    public MetaClassBuilder detail(T detail) {
        this.detail = detail;
        return this;
    }
}
